﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Repository.FileSystem.WikiNamespaceFileSystemRepository
{
    public class UpdateEntityFacts
    {
        [Fact]
        public void Checks_Whether_Namespace_Directory_Exists()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---{0}", wikiNamespace.Id) });
            fileSystem.Setup(x => x.FileExists(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id))).Returns(true);

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiNamespaceRepository.UpdateEntity(wikiNamespace);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Throws_Exception_If_Namespace_Directory_Does_Not_Exist()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { });

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.NamespaceDoesNotExistException>(
                () => wikiNamespaceRepository.UpdateEntity(wikiNamespace));
        }

        [Fact]
        public void Checks_Whether_Namespace_File_Exists()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---{0}", wikiNamespace.Id) });
            fileSystem.Setup(x => x.FileExists(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id))).Returns(true);

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiNamespaceRepository.UpdateEntity(wikiNamespace);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Throws_Exception_If_Namespace_File_Does_Not_Exist()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---{0}", wikiNamespace.Id) });
            fileSystem.Setup(x => x.FileExists(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id))).Returns(false);

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            Assert.Throws<MvcWiki.Exceptions.NamespaceDoesNotExistException>(
                () => wikiNamespaceRepository.UpdateEntity(wikiNamespace));
        }

        [Fact]
        public void Renames_Namespace_Directory_If_Name_Has_Been_Changed()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { String.Format("c:\\path\\NamespaceOld---{0}", wikiNamespace.Id) });
            fileSystem.Setup(x => x.MoveDirectory(String.Format("c:\\path\\NamespaceOld---{0}", wikiNamespace.Id), String.Format("c:\\path\\Namespace---{0}", wikiNamespace.Id)));
            fileSystem.Setup(x => x.FileExists(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id))).Returns(true);

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiNamespaceRepository.UpdateEntity(wikiNamespace);

            fileSystem.VerifyAll();
        }

        [Fact]
        public void Writes_Namespace_Xml_File()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup { Name = "WikiMarkup1" }
            };

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            var wikiMarkupProvider = new Mock<MvcWiki.Markup.IWikiMarkupProvider>();
            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var fileSystem = new Mock<MvcWiki.Repository.FileSystem.IFileSystemWrapper>();
            fileSystem.Setup(x => x.GetDirectories("c:\\path", String.Format("*---{0}", wikiNamespace.Id))).Returns(new string[] { String.Format("c:\\path\\Namespace---{0}", wikiNamespace.Id) });
            fileSystem.Setup(x => x.FileExists(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id))).Returns(true);
            fileSystem.Setup(x => x.WriteToFile(String.Format("c:\\path\\Namespace---{0}\\wikinamespace.xml", wikiNamespace.Id), "<wikinamespace><wikimarkup>WikiMarkup1</wikimarkup></wikinamespace>"));

            var wikiNamespaceRepository = new MvcWiki.Repository.FileSystem.WikiNamespaceFileSystemRepository(repositoryFactory.Object, wikiMarkupProvider.Object, unitOfWork.Object, "c:\\path", fileSystem.Object);

            wikiNamespaceRepository.UpdateEntity(wikiNamespace);

            fileSystem.VerifyAll();
        }
    }
}
